#pragma once

#include "ZSocket.h"
#include "ZNetworkReceiveBuffer.h"
#include "ZNetworkSendBuffer.h"
#include "ZPoolObject.h"
#include <boost/shared_ptr.hpp>
#include <boost/atomic.hpp>

namespace	Z	{

//------------------------------------------------------------------------------------------------------------------------
struct	MessageReceiver;

class	_ZNetworkApi	AsyncSocket
	:	public Socket
{
private:
	struct	Overlapped
		:	public OVERLAPPED,
			public PoolObject
	{
	};
public:
	AsyncSocket(SOCKET so, NetworkId kNetworkId);
	virtual	~AsyncSocket();
	virtual	bool	create();
	bool	send(Stream* pStream);
	bool	receive();
	virtual	NetworkId	getNetworkId()	const	{	return mNetworkId;		}
	bool	onReceiveComplete(size_t bytesTransferred, MessageReceiver& kMessageReceiver);
	bool	onSendComplete(size_t bytesTransferred);
	void	reference()	{	mReference.fetch_add(1, boost::memory_order_relaxed);	}
	bool	unreference()	{	return mReference.fetch_sub(1, boost::memory_order_release) == 1;	}
	bool	isReceive(OVERLAPPED* pOverlapped)	const	{	return mReceiveOverlapped == pOverlapped;	}
	bool	isSend(OVERLAPPED* pOverlapped)	const	{	return mSendOverlapped == pOverlapped;	}
private:
	bool	doSend();

private:
	NetworkId	mNetworkId;
	mutable	boost::atomic<int>	mReference;
	NetworkReceiveBuffer	mReceiveBuffer;
	NetworkSendBuffer	mSendBuffer;
	Overlapped*	mReceiveOverlapped;
	Overlapped*	mSendOverlapped;
	mutex_t	mSendLock;
};

}